#ifndef __MY_SERVICE__
#define __MY_SERVICE__

#include "data.hpp"
#include "Config.hpp"
#include "httplib.h"
#include <sstream>
extern Cloud_up::DataManager *_Dm;

//声明多文件下可以使用
namespace Cloud_up
{

    class Service
    {
    private:
        int _server_port;   //端口
        std::string _server_ip;  //地址
        std::string _url_prefix; //
        httplib::Server _svr;   //服务器实例

    public:

        // 上传  （请求，响应）
        static void Upload(const httplib::Request &req, httplib::Response &res)
        {
            auto ret = req.has_file("file"); // 判断是否有文件 file字段
            // 如果请求没有file 则状态设置为400
            if (ret == false)
            {
                std::cout << "not file upload" << std::endl;
                res.status = 400;
                return;
            }
            // file.content内容  file.filename文件名
            // 获取文件字段中 文件的数据
            //类型，map<>
            const auto &file = req.get_file_value("file");
            // 获取备份文件夹路径
            std::string back_dir = Config::GetInstance()->GetBackDir();

            // 备份路径+文件名
            std::string real_path = back_dir + Filetool(file.filename).FileName();
            // 备份文件
            Filetool ft(real_path);
            // file.content写道real_path
            ft.SetContent(file.content);

            BackupInfo val;
            // 更新数据
            val.NewBackupInfo(real_path);
            _Dm->Insert(val);
            return;
        }
        //返回 c_str 中的时间
        static std::string TimetoStr(time_t t)
        {
            std::string time = std::ctime(&t);
            return time;
        }

        static void List(const httplib::Request &req, httplib::Response &res)
        {
            // std::cout<<"____________"<<std::endl;
            // std::vector<BackupInfo> v;
            // _Dm->GetAll(&v);
            // for (auto &a : v)
            // {
            //     std::cout << a._real_path << std::endl;
            // }
            // std::stringstream ss;
            // ss<<"<html><head><title>Download</title></head>";
            // ss<<"<body><h1>Download</hl><table>";
            // ss<<"<tr>";
            // ss<<"<td><a href='url'>""1.txt""</a></td>";
            // ss<<"<td align='right'>""100""</td>";
            // ss<<"<td align='right'>""100""K</td>";
            // ss<<"</tr>";
            // ss<<"</table></body></html>";
            // res.body = ss.str(); // 转换
            // res.set_header("Content-Type", "text/html");
            // res.status = 200;

            // 1.获取所有备份数据
            std::vector<BackupInfo> v;
            _Dm->GetAll(&v);
            for (auto &a : v)
            {
                std::cout << a._real_path << std::endl;
            }

            std::stringstream ss;
            // // // 2.构建html页面
            // // // 2.1固定头
            ss << "<html><head><title>Download</title></head>";
            ss << "<body><h1>Download</hl><table>";
            // // // // 2.2文件列表
            for (auto &a : v)
            {
                ss << "<tr>";
                std::string file_name = Filetool(a._real_path).FileName();
                ss << "<td><a href='";
                ss << a._url_path.c_str();
                ss << "'>";
                ss << file_name.c_str();
                ss << "</a></td>";
                ss << "<td align='right'>";
                ss << TimetoStr(a._mtime).c_str();
                ss << "</td>";
                ss << "<td align='right'>";
                ss << a._fsize / 1024;
                ss << "k</td>";
                ss << "</tr>";
            }
            ss << "</table></body></html>";
            res.body = ss.str(); // ss字节流传入响应body
            res.set_header("Content-Type", "text/html");
            res.status = 200;
            return;
        }

        static std::string GetTag(const BackupInfo &val)
        {
            // 使用 filename-size-mtime去标识头部
            Filetool ft(val._real_path);
            std::string tag = ft.FileName();
            tag += "-";
            tag += std::to_string(val._fsize);
            tag += "-";
            tag += std::to_string(val._mtime);
            // std::cout << tag << std::endl;

            return tag;
        }




        static void DownLoad(const httplib::Request &req, httplib::Response &res)
        {
            // 获取资源路径 path
            // 根据资源路径获取备份信息
            BackupInfo val;
            // std::cout<<val<<std::endl;
            // std::cout << req.path << std::endl;

            _Dm->GetOneByURL(req.path, &val);
            //如果是热点文件 把源文件删除
            if (val._pack_flag == true)
            {
                Filetool ft(val._pack_path);
                ft.UnCompress(val._real_path);
                ft.ReMove();
                val._pack_flag = false;
                _Dm->Update(val);
            }



            //源文件
            Filetool ft(val._real_path);
            bool ret = false;
            std::string cur;

            //判断请求头是否有 If-Range字段
            if (req.has_header("If-Range"))
            {
                //获取字段的数据
                cur = req.get_header_value("If-Range");
                if (cur == GetTag(val))//如果请求头数据满足自定义数据
                {
                    ret = true;
                }
            }

            // std::cout<<req.get_header_value("If-Range")<<std::endl;
            // std::cout<<"--------------------"<<std::endl;

            // std::cout<<GetTag(val)<<std::endl;
            // 读取文件数据放入 res中



            // 自定义设置相应字段
            if (ret == false)
            {
                
                ft.GetContent(&res.body);//读取源文件数据
                res.set_header("Accept-Ranges", "bytes");//读取字节
                res.set_header("ETag", GetTag(val));//获取信息
                res.set_header("Content-Type", "application/octet-stream");//字节流
                res.status = 200;

            }
            else
            {
                // 断点续传功能
                ft.GetContent(&res.body);
                res.set_header("Accept-Ranges", "bytes");
                res.set_header("ETag", GetTag(val));
                res.set_header("Content-Type", "application/octet-stream");//字节流
                res.status = 206;
            }
            return ;
        }




    public:
        Service()
        {
            // 获取基本配置
            Config *cf = Config::GetInstance();
            _server_ip = cf->GetServerIp();
            _server_port = cf->GetServerPort();
            _url_prefix = cf->GetUrlPrefix(); // 前缀
        }

        bool RunModule()
        {
            _svr.Post("/upload", Upload); //使用post请求 关联Upload上传函数
            _svr.Get("/listshow", List);  //使用get请求 关联Upload上传函数
            _svr.Get("/", List);
            // 正则表达式
            std::string download_prefix = _url_prefix + "(.*)";
            _svr.Get(download_prefix, DownLoad); //使用get方法取请求
            _svr.listen(_server_ip.c_str(), _server_port); //监听
            
            return true;
        }
    };
}
#endif
